package top.hudk.sql.generator;

import lombok.extern.slf4j.Slf4j;
import top.hudk.sql.domin.ShardingResult;
import top.hudk.sql.domin.DataMate;
import top.hudk.sql.strategy.abstracts.ShardingStrategy;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

/**
 * 请输入描述信息
 * ShardingStrategy
 * @author HuDongkang
 * @date 2022/9/1 10:37
 */
@Slf4j
public abstract class AbstractSqlGenerator<D extends DataMate<V>, S extends ShardingStrategy, V> {

    protected  static final Map<String, List<String >> SQL_GEN_MAP = new HashMap<>();

    public void gen(){
        List<D> dataMateList = getDataMateList();
        for(D dataMate : dataMateList){
            ShardingResult sharding = doShardingStrategy(getShardingStrategy(), dataMate.getShardingValue());
            String format = format(sharding, dataMate);
            addSqlGenMap(sharding, format);
        }
        printSql();
    }

    private void addSqlGenMap(ShardingResult sharding, String format){
        if(Objects.isNull(SQL_GEN_MAP.get(sharding.getDbNo()))){
            List<String> sqlList = new ArrayList<>();
            SQL_GEN_MAP.put(sharding.getDbNo(), sqlList);
        }
        SQL_GEN_MAP.get(sharding.getDbNo()).add(format);
    }

    protected void printSql(){
        System.out.println("**********");
        System.out.println("Sql生成结果：");
        Set<String> strings = SQL_GEN_MAP.keySet();
        for(String key : strings){
            List<String> sqlGen = SQL_GEN_MAP.get(key);
            for(String sql : sqlGen){
                System.out.println(sql);
            }
        }
    }


    /**
     * 执行分库分表策略
     * @param shardingStrategy 分库分表策略对象
     * @param shardingValue 分库分表属性的值
     * @return 分库分表结果对象
     */
    protected abstract ShardingResult doShardingStrategy(S shardingStrategy, V shardingValue);


    /**
     * 格式化，并返回格式化的字符串文本内容
     * @param shardingResult 分库分表结果
     * @param dataMate 数据对象
     * @return 格式化的文本内容
     */
    protected abstract String format(ShardingResult shardingResult, D dataMate);


    /**
     * 返回一个分库分表策略对象
     * @return 分库分表策略对象
     */
    protected abstract S getShardingStrategy();

    /**
     * 返回要进行分库分表的元数据
     * @return 元数据
     */
    protected abstract List<D> getDataMateList();
}
